import 'package:enum_to_string/enum_to_string.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mode/ui/ConvertDemo.dart';
import 'package:flutter_mode/ui/QuiverAsyncDemo.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get_storage/get_storage.dart';
import 'package:logger/logger.dart';
import 'package:quiver/cache.dart';
import 'package:quiver/check.dart';
import 'package:quiver/collection.dart';
import 'package:quiver/core.dart';
import 'package:quiver/iterables.dart';
import 'package:quiver/pattern.dart';
import 'package:quiver/strings.dart';
import 'package:quiver/time.dart';
import 'package:url_launcher/url_launcher.dart';

import '../utils.dart';

/// kiven 2021/8/20
class DataDealDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _DataDealDemoState();
  }
}

class _DataDealDemoState extends State<DataDealDemo> {
  final box = GetStorage();
  static const key = 'GetStorage_test_key';

  final logger = Logger();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    box.listenKey(key, (value) {
      showToast('GetStorage值改变, $value');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('数据'),
          centerTitle: true,
        ),
        body: SingleChildScrollView(
          child: Wrap(
            spacing: 8,
            runSpacing: 4,
            children: [
              addTitle('get_storage, 使用前需要 GetStorage.init()'),
              addAction('读写值', () {
                final int v = box.read(key) ?? 0;
                box.write(key, v + 1);
              }),
              addAction('移除值', () {
                box.remove(key);
              }),
              addTitle('SharedPreferences'),
              addAction('读写值', () async {
                final sp = await getSharedPreferences();
                var v = sp.getInt(key) ?? 0;
                v++;
                sp.setInt(key, v);
                showToast('SharedPreferences值改变, $v');
              }),
              addAction('移除值', () async {
                final sp = await getSharedPreferences();
                sp.remove(key);
              }),
              addTitle('quiver'),
              addAction('strings', quiverStringsDemo),
              addAction('time', quiverTimeDemo),
              addAction('正则', () {
                // 它的正则规则有些不一样，最好看一下Glob类上边的注解
                print('- Glob');
                final glob = Glob('a*?');
                print(glob.hasMatch('aaccbbdzz'));
                print(glob.allMatches('aaccbbdzz, aaac').map((e) => e.input));

                print('- escapeRegex');
                print(escapeRegex('^a*?'));

                print('- matchesFull');
                print(matchesFull('a*?', 'aaac')); // 没测试明白
                print(glob.allMatches('aaac').map((e) => e.input));
              }),
              addAction(
                  'async', () => pushMaterial(context, QuiverAsyncDemo())),
              addAction('cache', () {
                final map = MapCache<int, int>.lru(maximumSize: 3);
                // final map = MapCache<int, int>();// lru 可限制大小
                map.set(1, 1);
                map.set(2, 2);
                map.get(1).then(print);
                map.set(3, 3);
                map.set(4, 4);
                map.get(1).then(print);
                map.get(2).then(print);
                map.get(3).then(print);
                map.get(4).then(print);
                map.get(5).then(print);
              }),
              addAction('check', () async {
                final r = await showMyBottomSheet(context, [
                  'checkArgument',
                  'checkListIndex',
                  'checkNotNull',
                  'checkState',
                ]);
                try {
                  switch (r) {
                    case 0:
                      checkArgument(false, message: '测试checkArgument');
                      break;
                    case 1:
                      checkListIndex(8, 2, message: '测试checkListIndex');
                      break;
                    case 2:
                      // checkNotNull() 过期，测试推荐方法
                      ArgumentError.checkNotNull(null, 'nameKK');
                      break;
                    case 3:
                      checkState(false, message: '测试checkState');
                      break;
                  }
                } catch (e) {
                  print(e);
                }
              }),
              addAction('collection', quiverCollectionDemo),
              addAction('core', () {
                print('- Optional');
                final optional = Optional.of(2);
                print(optional.value);

                print('- hash2');
                print(hash2(optional, 1));

                print('- hash3');
                print(hash3(optional, 1, 1));

                print('- hash4');
                print(hash4(optional, 1, 1, 1));

                print('- hashObjects');
                print(hashObjects([optional, 1, 1, 1]));
              }),
              addAction('iterables', () {
                quiverIterablesDemo();
              }),
              addTitle('其他'),
              addAction('EnumToString', () {
                print(Toast.LENGTH_LONG);
                print(Toast.values);

                String result = EnumToString.convertToString(Toast.LENGTH_LONG);
                //result = 'testValue1'
                print(result);

                print(EnumToString.convertToString(Toast.LENGTH_LONG,
                    camelCase: true));

                print(EnumToString.fromString(Toast.values, "LENGTH_LONG"));
                print(EnumToString.fromString(Toast.values, "LENGTH long",
                    camelCase: true));

                print(EnumToString.toList(Toast.values));
                print(EnumToString.toList(Toast.values, camelCase: true));

                print(EnumToString.fromList(
                    Toast.values, ["LENGTH_LONG", "Value2"]));
              }),
              addAction('logger',
                  () => logger.d('这是logger库输出的测试信息。该库好像不完善，部分level输出显示多余的字符。')),
              addAction('convert', () {
                pushMaterial(context, ConvertDemo());
              }),
              addAction('equatable', () {
                final a = A(1, '2');
                final b = B(1, '2');

                print(a == A(1, '2'));
                print(b == B(1, '2'));
              }),
              addAction('url_launcher', () async {
                final _url = 'https://www.baidu.com';
                await canLaunch(_url)
                    ? await launch(_url)
                    : throw 'Could not launch $_url';
              }),
            ],
          ),
        ));
  }

  addTitle(String title) {
    return Center(
      child: Text(title),
    );
  }

  addAction(String title, Function() action) {
    return ElevatedButton(
      onPressed: action,
      child: Text(title),
    );
  }

  quiverStringsDemo() {
    print('- isBlank');
    print(isBlank(' \n'));
    print(isBlank(' \n h'));
    print(isBlank(null));

    print('- isNotBlank');
    print(isNotBlank(' \n'));
    print(isNotBlank(' \n h'));
    print(isNotBlank(null));

    print('- isEmpty');
    print(isEmpty(' \n'));
    print(isEmpty(' \n h'));
    print(isEmpty(null));

    print('- isNotEmpty');
    print(isNotEmpty(' \n'));
    print(isNotEmpty(' \n h'));
    print(isNotEmpty(null));

    print('- isWhitespace'); //判断的是字符对应的数字
    print(isWhitespace('\n'.codeUnits.first));
    print(isWhitespace(' '.codeUnits.first));
    print(isWhitespace('1'.codeUnits.first));

    print('- loop');
    print(loop('abcdefghijklmn', 2));
    print(loop('abcdefghijklmn', 2, 9));

    print('- isDigit'); //判断的是字符对应的数字
    print(isDigit('1'.codeUnits.first));
    print(isDigit('a'.codeUnits.first));

    print('- equalsIgnoreCase');
    print(equalsIgnoreCase('aBcD', 'AbCd'));
    print(equalsIgnoreCase('aBcD', 'AbCd`'));

    print('- compareIgnoreCase');
    print(compareIgnoreCase('aBcD', 'AbCd'));
    print(compareIgnoreCase('BaBcD', 'AbCd'));

    print('- center');
    print(center('AAA', 9, 'x'));
    print(center('AAA', 4, 'x'));
  }

  quiverTimeDemo() {
    print('- 时间长度');
    print(aMicrosecond.inMicroseconds);
    print(aMillisecond.inMicroseconds);
    print(aSecond.inMicroseconds);
    print(aMinute.inMicroseconds);
    print(anHour.inMicroseconds);
    print(aDay.inMicroseconds);
    print(aWeek.inMicroseconds);

    print('- isLeapYear');
    var a = <int>[];
    for (int i = 2000; i < 3000; i++) {
      if (isLeapYear(i)) {
        a.add(i);
      }
    }
    print(a);
    print(a.where((element) => element % 100 == 0));

    print('- systemTime');
    print(systemTime());

    print('- daysInMonth');
    print(daysInMonth(2021, 2));
    print(systemTime());

    print('- clampDayOfMonth');
    print(clampDayOfMonth(year: 2021, month: 2, day: 50));

    print('- Clock');
    final clock = Clock.fixed(systemTime());
    print(clock.now());
    print(clock.ago(days: 10));
    print(clock.weeksAgo(2));
    print(clock.weeksFromNow(2));
  }

  quiverCollectionDemo() {
    showMyBottomSheet2(context, {
      'AvlTreeSet': () {
        print('- AvlTreeSet 正确用法应该是在查找上，这里就不测试查找性能了');
        final set = AvlTreeSet<int>(comparator: (a, b) => b.compareTo(a));
        set.addAll([1, 2, 3, 23, 21, 43, 32]);
        print(set.toList(growable: false));
      },
      'HashBiMap': () {
        print('- HashBiMap. k, v 都不能出现同值，否则报错。HashBiMap仅支持1对1');
        final hashMap = HashBiMap();
        hashMap.addAll({
          'k1': 'v1',
          'k2': 'v2',
          'k3': 'v3',
          // 'k4': 'v2'// k, v 都不能出现同值，否则报错。HashBiMap仅支持1对1
        });
        print(hashMap.entries);
        print(hashMap.inverse.entries);
      },
      'LinkedLruHashMap': () {
        print('- LinkedLruHashMap. 超过maximumSize个，会更加lru算法删除多余的');
        final llhm = LinkedLruHashMap<int, int>(maximumSize: 3);
        llhm[1] = 1;
        llhm[2] = 2;
        llhm[3] = 3;
        print(llhm[1]);
        llhm[4] = 4; // 超过3个，会更加lru算法删除一个
        print(llhm[1]);
        print(llhm[2]);
        print(llhm[3]);
        print(llhm[4]);
      },
      'ListMultimap': () {
        print('- ListMultimap.');
        final map = ListMultimap<String, int>();
        map.add('a', 1);
        map.add('a', 2);
        map.add('b', 3);
        map.addValues('c', [4, 4, 5, 6, 7, 7]);
        map.forEach((key, value) {
          print('$key = $value');
        });
      },
      'SetMultimap': () {
        print('- SetMultimap. 与ListMultimap的区别是同一个key的value不能重复。');
        final map = SetMultimap<String, int>();
        map.add('a', 1);
        map.add('a', 2);
        map.add('b', 3);
        map.addValues('c', [4, 4, 5, 6, 7, 7]);
        map.add('d', 6);
        map.forEach((key, value) {
          print('$key = $value');
        });
      },
      'indexOf': () {
        print(indexOf([1, 45, 45, 65, 8, 9], (e) => e == 45));
      },
      'listsEqual': () {
        print(listsEqual([A(3, 'f')], [A(3, 'f')]));
      },
      'mapsEqual': () {
        print(mapsEqual({'aa': A(3, 'f')}, {'aa': A(3, 'f')}));
      },
      'setsEqual': () {
        print(setsEqual(Set.from([A(3, 'f')]), Set.from([A(3, 'f')])));
      }
    });
  }

  quiverIterablesDemo() {
    showMyBottomSheet2(context, {
      '原有Iterable': () {
        print('- 原有Iterable');
        print(Iterable.castFrom([3, 5, 9]).elementAt(2));
      },
      'EnumerateIterable': () {
        print('- EnumerateIterable');
        print(EnumerateIterable([3, 7, 0, 3, 5]).elementAt(2));
      },
      'EnumerateIterator': () {
        print('- EnumerateIterator');
        var i = EnumerateIterator(Iterable.castFrom([3, 5, 9]).iterator);
        i.moveNext();
        print(i.current);
      },
      'GeneratingIterable 同 generate': () {
        print('- GeneratingIterable, 根据前一个值获取后一个值');
        print(GeneratingIterable<int>(() => 5, (i) => i * i));
        // (5, 25, 625, 390625, 152587890625, 3273344365508751233, ...)
      },
      'concat 所以子拼接成新的数组': () {
        print(concat([
          [1, 2, 3],
          [4, 5],
          [5]
        ]));
        // (1, 2, 3, 4, 5, 5)
      },
      'count 无限增长数组': () {
        print(count(4, 10));
        // (4, 14, 24, 34, 44, 54, 64, 74, 84, 94, 104, 114, 124, 134, 144, 154, 164, ...)
      },
      'cycle 无限循环遍历数组': () {
        print(cycle([1, 2, 3, 4, 5]));
        // (1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...)
      },
      'generate 同 GeneratingIterable': () {
        print(generate(() => 5, (o) => o * o));
        // (5, 25, 625, 390625, 152587890625, 3273344365508751233, ...)
      },
      'range': () {
        print(range(5));
        // (0, 1, 2, 3, 4)
        print(range(15, 24, 2));
        // (15, 17, 19, 21, 23)
      },
      'enumerate 给数组元素绑定编号': () {
        print(enumerate(['a', 'b', 'c']));
        // ((0, a), (1, b), (2, c))
      },
      'extent 提取最小最大值': () {
        final r = extent([6, 9, 0, 100]);
        print('min = ${r.min}, max = ${r.max}');
      },
      'max': () {
        print(max([6, 9, 0, 100]));
      },
      'min': () {
        print(min([6, 9, 0, 100]));
      },
      'merge': () {
        print(merge([[1, 2, 3], [3, 4, 5]]));
        // [1, 2, 3, 3, 4, 5]
      },
      'partition 拆分数组到指定大小': () {
        print(partition([6, 9, 0, 100, 4], 2));
        // ([6, 9], [0, 100], [4])
      },
      'zip 重组数组，不是压缩数组': () {
        // 每个子数组的第n个元素组成一个新的子数组
        print(zip([[1, 2, 3], ['a', 'b' , 'c']]));
        // ([1, a], [2, b], [3, c])
        print(zip([[1, 2, 3], ['a', 'b' , 'c'], ['γ']]));
        // ([1, a, γ])
      },
    });
  }
}

class A extends Equatable {
  final int a;
  final String b;

  A(this.a, this.b);

  @override
  List<Object?> get props => [a, b];
}

class B {
  final int a;
  final String b;

  B(this.a, this.b);
}
